package com.nidu.demo.online.executor.query;

import com.alibaba.cola.dto.SingleResponse;
import com.nidu.demo.common.enums.BooleanEnum;
import com.nidu.demo.common.enums.StatusEnum;
import com.nidu.demo.log.gateway.LoginLogGateway;
import com.nidu.demo.log.model.LoginLog;
import com.nidu.demo.log.model.LoginLogCriteria;
import com.nidu.demo.oauth2.gateway.OAuth2AccessTokenGateway;
import com.nidu.demo.oauth2.model.OAuth2AccessToken;
import com.nidu.demo.online.dto.OnlineUserStatisticsCO;
import com.nidu.demo.user.gateway.UserGateway;
import com.nidu.demo.user.model.User;
import com.nidu.demo.user.model.UserCriteria;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 站内信消息单个查询执行器
 *
 * @author auto
 */
@Component
@RequiredArgsConstructor
public class OnlineUserSingleQryExe {

    private final OAuth2AccessTokenGateway accessTokenGateway;
    private final LoginLogGateway loginLogGateway;
    private final UserGateway userGateway;

    public SingleResponse<OnlineUserStatisticsCO> getOnlineUserStatistics() {
        OnlineUserStatisticsCO statistics = new OnlineUserStatisticsCO();
        statistics.setStatisticsTime(LocalDateTime.now());

        // 1. 获取当前在线用户总数（基于有效的访问令牌）
        statistics.setTotalOnlineUsers(getTotalOnlineUsersCount());

        // 2. 统计今日登录用户数
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime todayEnd = todayStart.plusDays(1);
        statistics.setTodayLoginUsers(getTodayLoginUserCount(todayStart, todayEnd));

        // 3. 统计今日新增用户数（需要查询用户表的创建时间）
        statistics.setTodayNewUsers(getTodayNewUserCount(todayStart, todayEnd));

        // 4. 统计本周活跃用户数
        LocalDateTime weekStart = LocalDateTime.now().minusDays(7);
        statistics.setWeeklyActiveUsers(getActiveUserCount(weekStart, LocalDateTime.now()));

        // 5. 统计本月活跃用户数
        LocalDateTime monthStart = LocalDateTime.now().minusDays(30);
        statistics.setMonthlyActiveUsers(getActiveUserCount(monthStart, LocalDateTime.now()));

        return SingleResponse.of(statistics);
    }

    /**
     * 获取在线人数
     * @return
     */
    private Long getTotalOnlineUsersCount() {
        Map<Long, List<OAuth2AccessToken>> longListMap = accessTokenGateway.getAllValidTokens();
        return (long) longListMap.size();
    }

    /**
     * 获取今日登录用户数
     * @param startTime
     * @param endTime
     * @return
     */
    private Long getTodayLoginUserCount(LocalDateTime startTime, LocalDateTime endTime) {
        LoginLogCriteria criteria = new LoginLogCriteria();
        criteria.setCreateTime(new LocalDateTime[]{startTime, endTime});
        criteria.setResult(BooleanEnum.TRUE.getValue());
        List<LoginLog> todayLogins = loginLogGateway.listByCondition(criteria);
        return todayLogins.stream()
                .map(LoginLog::getUserId)
                .distinct()
                .count();
    }

    /**
     * 获取今日新增用户数
     * @param startTime
     * @param endTime
     * @return
     */
    private Long getTodayNewUserCount(LocalDateTime startTime, LocalDateTime endTime) {
        UserCriteria userCriteria = new UserCriteria();
        userCriteria.setCreateTime(new LocalDateTime[]{startTime, endTime});
        userCriteria.setStatus(StatusEnum.ENABLE.getValue());
        List<User> userList = userGateway.listByCondition(userCriteria);
        return (long) userList.size();
    }

    /**
     * 获取活跃用户数
     * @param startTime
     * @param endTime
     * @return
     */
    private Long getActiveUserCount(LocalDateTime startTime, LocalDateTime endTime) {
        LoginLogCriteria criteria = new LoginLogCriteria();
        criteria.setCreateTime(new LocalDateTime[]{startTime, endTime});
        criteria.setResult(true);
        List<LoginLog> activeLogins = loginLogGateway.listByCondition(criteria);
        return activeLogins.stream()
                .map(LoginLog::getUserId)
                .distinct()
                .count();
    }

}
